//
//  MazeView.m
//  Maze
//
//  Created by 奕 朱 on 11-3-30.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import "MazeView.h"



@implementation MazeView
@synthesize numOfHorizontalCells = _numOfHorizontalCells;
@synthesize numOfVerticalCells = _numOfVerticalCells;
@synthesize cellData = _cellData;
@synthesize worldImage = _worldImage;
@synthesize startLocation = _startLocation;
@synthesize playerLocation = _playerLocation;
@synthesize playerImage = _playerImage;


- (id)initWithFrame:(CGRect)frame {
    
    self = [super initWithFrame:frame];
    if (self) {
		_numOfHorizontalCells = 0;
		_numOfVerticalCells = 0;
		_cellData = nil;
		_worldImage = nil;
		_startLocation = CGPointMake(0, 0);
		_playerLocation = CGPointMake(0, 0);
		_playerImage = [[UIImage imageNamed:kPlayerImageName] retain];
		
		[self setBackgroundColor:[UIColor blackColor]];
    }
    return self;
}

/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
    // Drawing code.
}
*/

- (void)dealloc {
	[_cellData release];
	[_worldImage release];
	[_playerImage release];
    [super dealloc];
}

- (BOOL) loadFromContentsOfURL:(NSURL *)fileURL {

	[self setNumOfVerticalCells: 0];
	[self setNumOfHorizontalCells: 0];
	[self setCellData: nil];
	[self setStartLocation: CGPointMake(0, 0)];
	[self setPlayerLocation: CGPointMake(0, 0)];
	
	NSString *fileData;
	fileData = [NSString stringWithContentsOfURL:fileURL 
										encoding:NSUTF8StringEncoding 
										   error: NULL];
	
	if (!fileData) {
		return NO;
	}
	
	NSUInteger cellCountH = 0;
	NSMutableData *workingCellData = nil;
	
	NSArray *lineArray;
	lineArray = [fileData componentsSeparatedByString: @"\n"];
	
	if (!lineArray || [lineArray count] == 0) {
		return NO;
	}
	
	NSString *firstLine;
	firstLine = [lineArray objectAtIndex: 0];
	
	NSArray *firstLineStrArray;
	firstLineStrArray = [firstLine componentsSeparatedByString: @","];
	
	cellCountH = [firstLineStrArray count];
	if (cellCountH == 0) {
		return NO;
	}
	
	NSUInteger dataSize;
	dataSize = cellCountH * [lineArray count];
	workingCellData = [NSMutableData dataWithLength: dataSize];
	if (!workingCellData) {
		return NO;
	}
	
	uint8_t *cellPtr = (uint8_t *)[workingCellData mutableBytes];
	
	for (NSString *lineStr in lineArray) {
		NSAutoreleasePool *pool;
		pool = [[NSAutoreleasePool alloc] init];
		
		[self parseLineString: lineStr 
					  writeTo: cellPtr];
		
		cellPtr += cellCountH;
		
		[pool release];
	}
	
	[self setNumOfVerticalCells: [lineArray count]];
	[self setNumOfHorizontalCells: cellCountH];
	[self setCellData: workingCellData];
	
	[self createWorldImage];
	
	
	CGPoint startLocation;
	startLocation = [self findStartCell];
	[self setStartLocation: startLocation];
	[self setPlayerLocation: startLocation];
	
	return YES;
	
}

- (void) parseLineString:(NSString *)lineString 
				 writeTo:(uint8_t *)dstPtr {
	NSArray *cellStrArray;
	cellStrArray = [lineString componentsSeparatedByString: @","];
	
	uint8_t *p = dstPtr;
	
	for (NSString *str in cellStrArray) {
		
		*p = (uint8_t)[str intValue];
		
		p++;
	}
	
	
}

- (void) createWorldImage {

	[self setWorldImage: nil];
	
	NSUInteger cellCountH = self.numOfHorizontalCells;
	NSUInteger cellCountV = self.numOfVerticalCells;
	NSData *cellData = self.cellData;
	
	if (cellCountH == 0 ||
		cellCountV == 0 ||
		cellData == nil ||
		[cellData length] == 0) {
		return;
	}
	
	NSArray *cellImageArray;
	cellImageArray = [self loadCellImageArray];
	
	CGSize imageSize;
	imageSize = CGSizeMake(kCellImageSize * cellCountH,
						   kCellImageSize * cellCountV);
	
	UIGraphicsBeginImageContext(imageSize);
	
	const uint8_t *p = (const uint8_t *) [cellData bytes];
	NSUInteger h, v;
	NSNull *null = [NSNull null];
	
	for (v = 0; v < cellCountV; v++) {
		
		NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
		
		for (h = 0; h < cellCountH; h++) {
			
			UIImage *cellImage;
			cellImage = [cellImageArray objectAtIndex: *p];
			
			if (![cellImage isEqual: null]) {
				
				CGPoint pt = CGPointMake(kCellImageSize * h,
										 kCellImageSize * v);
				[cellImage drawAtPoint: pt];
				
			}
			
			p++;
			
		}
		
		[pool release];
		
	}
	
	UIImage *worldImage;
	worldImage = UIGraphicsGetImageFromCurrentImageContext();
	
	[self setWorldImage: worldImage];
	
	UIGraphicsEndImageContext();
	
}

- (NSArray *) loadCellImageArray {

	NSMutableArray *theArray = [NSMutableArray array];
	
	UIImage *img;
	
	img = [UIImage imageNamed: kWallImageName];
	
	if (img) {
		[theArray addObject: img];
	} else {
		[theArray addObject:[NSNull null]];
	}
	
	img = [UIImage imageNamed: kGroundImageName];
	
	if (img) {
		[theArray addObject: img];
	} else {
		[theArray addObject: [NSNull null]];
	}
	
	img = [UIImage imageNamed: kGroundImageName];
	
	if (img) {
		[theArray addObject: img];
	} else {
		[theArray addObject: [NSNull null]];
	}

	img = [UIImage imageNamed: kGoalImageName];
	if (img) {
		[theArray addObject: img];
	} else {
		[theArray addObject: [NSNull null]];
	}
	
	return theArray;

}

- (CGPoint) findStartCell {

	const uint8_t *p = (const uint8_t *) [self.cellData bytes];
	NSUInteger h, v;
	
	NSUInteger cellCountV = self.numOfVerticalCells;
	NSUInteger cellCountH = self.numOfHorizontalCells;
	
	if (p) {
		
		for (v = 0; v < cellCountV; v++) {
			for (h = 0; h < cellCountH; h++) {
				if (*p == kCellTypeStart) {
					return CGPointMake(h, v);
				}
			}
			
			p++;
		}
		
	}
	
	return CGPointMake(0, 0);
	
}

- (CGRect) rectForCell:(CGPoint)cellLocation {

	return CGRectMake(cellLocation.x * kCellImageSize, 
					  cellLocation.y * kCellImageSize, 
					  kCellImageSize, kCellImageSize);
	
}

- (void) drawRect:(CGRect)rect {

	UIImage *img = self.worldImage;
	
	if (img) {
		
		CGPoint playerLocation = self.playerLocation;
		
		CGRect crt = [self rectForCell: playerLocation];
		
		CGSize sz = self.bounds.size;
		
		CGPoint topLeft;
		
		topLeft = CGPointMake(sz.width / 2 - (crt.origin.x + crt.size.width / 2), 
							  sz.height / 2 - (crt.origin.y + crt.size.height / 2));
		
		[img drawAtPoint: topLeft];
		
		crt.origin = CGPointMake(crt.origin.x + topLeft.x,
								 crt.origin.y + topLeft.y);
		[self.playerImage drawInRect: crt];
		
		
	}
	
}

@end
